package com.dkh.recommend.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dkh.recommend.dto.Result;
import com.dkh.recommend.entity.TbFollow;
import com.dkh.recommend.entity.TbMusic;
import com.dkh.recommend.entity.TbPlaylist;
import com.dkh.recommend.entity.TbRelate;
import com.dkh.recommend.mapper.TbFollowMapper;
import com.dkh.recommend.mapper.TbMusicMapper;
import com.dkh.recommend.mapper.TbPlaylistMapper;
import com.dkh.recommend.mapper.TbRelateMapper;
import com.dkh.recommend.service.ITbFollowService;
import com.dkh.recommend.service.RecommendService;
import com.dkh.recommend.utils.RecommendUtils;
import com.dkh.recommend.utils.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.dkh.recommend.utils.RedisConstants.PLAY_LIST_KEY;

@Service
@Slf4j
@Transactional
public class RecommendServiceImpl implements RecommendService {

    @Autowired
    private TbRelateMapper tbRelateMapper;
    @Autowired
    private  TbPlaylistMapper playlistMapper;

    @Autowired
    private TbFollowMapper followMapper;



    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private TbMusicMapper musicMapper;

    /**
     * //    根据用户最近加入播放列表的音乐进行推荐(ItemCF)(喜欢推荐)
     */
    @Override
    public Result LastPlayListRce() {
//        获取当前用户id
        Long userId = UserHolder.getUser().getUserId();
//        获取全部的评分关系表的内容
        List<TbRelate> allRelateList = tbRelateMapper.selectAllRelate();
//        获取最近加入播放队列的music_Id
        Long musicId = playlistMapper.getLastPlayListByuserId(userId);
//        根据推荐算法获取推荐的musciIdS
        List<Long> recommendations = RecommendUtils.itemCfRecommend(musicId, allRelateList);

        //        根据推荐算法得出的结果Ids进行过滤，得出推荐音乐List
//        List<TbMusic> musicList = musicData.stream().filter(e -> recommendations.contains(e.getMusicId())).collect(Collectors.toList());
        List<TbMusic> tbMusicList = musicMapper.slelectMusicByMusicIds(recommendations);
        return Result.ok(tbMusicList);
//        return recommendations;

    }


    /**
     *    根据用户推荐（UserCF）
     * @return
     */
    @Override
    public Result LastFollowRce() {
//        //        获取当前用户id
//        Long userId = UserHolder.getUser().getUserId();
//        //        获取全部的评分关系表的内容
//        List<TbRelate> allRelateList = tbRelateMapper.selectAllRelate();
//        //        获取最近关注的user_Id
//        Long lastFollowByUserId = followMapper.getLastFollowByUserId(userId);
//        //        根据推荐算法获取推荐的musciIdS
//        List<Long> recommendations = RecommendUtils.userCfRecommend(lastFollowByUserId, allRelateList);
//        if (recommendations.isEmpty() || recommendations.size() == 0){
////            recommendations 为空  返回未知错误
//        return Result.fail("推荐结果为空");
//        }
//        List<TbMusic> musicList = musicMapper.slelectMusicByMusicIds(recommendations);
//        return Result.ok(musicList);

        //        获取当前用户id
        Long userId = UserHolder.getUser().getUserId();
        //        获取全部的评分关系表的内容
        List<TbRelate> allRelateList = tbRelateMapper.selectAllRelate();
        //        获取最近关注的user_Id
//        Long lastFollowByUserId = followMapper.getLastFollowByUserId(userId);
        //        根据推荐算法获取推荐的musciIdS
        List<Long> recommendations = RecommendUtils.userCfRecommend(userId, allRelateList);
        if (recommendations.isEmpty() || recommendations.size() == 0){
//            recommendations 为空  返回未知错误
            return Result.fail("推荐结果为空");
        }
        List<TbMusic> musicList = musicMapper.slelectMusicByMusicIds(recommendations);
        return Result.ok(musicList);

    }

    /**
     * 根据当前用户关注的好友的播放列表进行推荐
     * @return
     */
    @Override
    public Result CommonFollowPlayListRec() {
        return null;
    }

    /**
     * 根据当前关注好友的播放队列的进行推荐
     * @return
     */
    @Override
    public Result FollowPlayListRec() {
        Long userId = UserHolder.getUser().getUserId();
//        根据用户Id查找用户关注列表ids
//        LambdaQueryWrapper<TbFollow> wrapper =new LambdaQueryWrapper<>();
//        wrapper.eq(TbFollow::getUserId,userId);
//        List<TbFollow> followList = followService.list(wrapper);
        List<Long> followUserIds = followMapper.selectFollowUserId(userId);
        if (followUserIds.isEmpty() || followUserIds.size() <= 0){
//            没有关注列表
            return Result.fail("还没有关注的好友");
        }
        String myKey = PLAY_LIST_KEY+userId;

//       推荐的 set集合（不可重复，无索引）
        Set<TbPlaylist> recPlayList = new HashSet<>();
//        根据ids查找获取播放列表，并和根据关注好友的播放队列进行推荐
        followUserIds.stream().forEach(followUserId->{
            //        redis缓存的key
            String key = PLAY_LIST_KEY+followUserId;
//            根据缓存mykey和关注好友的key获取被关注的人的播放队列获取音乐差集
            Set<String> differenceSet = stringRedisTemplate.opsForSet().difference(myKey, key);

            //           json转为TbPlaylistBean
            differenceSet.stream().forEach(difference->{
                TbPlaylist tbPlay = JSONUtil.toBean(difference, TbPlaylist.class);
                //            将音乐差集放入set集合（不可重复，无索引）自动去重
                recPlayList.add(tbPlay);
            });
//            List<TbPlaylist> tbPlaylists = BeanUtil.copyToList(differenceSet, TbPlaylist.class);
//            将音乐差集放入set集合（不可重复，无索引）自动去重
//            tbPlaylists.stream().forEach(tbPlaylist -> {
////                JSONUtil.toBean()
//                recPlayList.add(tbPlaylist);
//            });
//           recPlayList.addAll(tbPlaylists);
        });
//        List<TbPlaylist> recTbPlaylists = BeanUtil.copyToList(recPlayList, TbPlaylist.class);
        List<TbMusic> musicList = BeanUtil.copyToList(recPlayList, TbMusic.class);
        return Result.ok(musicList);
//        return Result.ok(recTbPlaylists);
    }


}
